package com.infinitus.activity.util;

import com.alibaba.fastjson.JSONObject;
import com.infinitus.activity.pojo.VO.ApiVo;
import com.infinitus.activity.pojo.VO.ReturnVo;
import org.macula.core.utils.HttpRequestUtils;
import org.macula.exception.MaculaException;
import org.macula.plugins.esb.openapi.OpenApiException;
import org.macula.plugins.esb.openapi.OpenApiHelper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;

/**
 * @author: luzhenjie
 * @create: 2019/4/1
 * @desc:  接口工具类
 */
public class ApiUtils {

    public static boolean invoking(String appId,String appSecret, String baseUrl,String loginPath,String dealerNo,String password) {
        boolean flag = false;

        MultiValueMap<String, String> signParam = new LinkedMultiValueMap<>();
        MultiValueMap<String, String> sendParam = new LinkedMultiValueMap<>(); //请求参数：卡号，密码
        sendParam.set("dealerNo",dealerNo);
        sendParam.set("password",password);

        //appId -> 对应channel 应用编号
        signParam.add("appId", appId);
        //appSecret -> 对应channel应用秘钥
        signParam.add("appSecret", appSecret);
        //path -> 请求路径
        signParam.add("path", loginPath);
        //endpoint -> 请求ip端口/域名
        //signParam.add("endpoint", "http://ydapi-staging-p.infinitus.com.cn");
        //signParam.add("endpoint", "http://172.20.72.25:6089");
        signParam.add("endpoint", baseUrl);
        //String sendType = "formPost";
        ResponseEntity<String> openApiResponse = postOrPutFormOpenApi(signParam, sendParam, String.class, HttpMethod.POST);
        //System.out.println("响应数据：\n"+new String(openApiResponse.getBody()));
        ReturnVo returnVo = JSONObject.parseObject(openApiResponse.getBody(), ReturnVo.class);
        if(returnVo.getApiVo() != null) {
            if(returnVo.getApiVo().isBizData()) {
                flag = true;
            }
        }
        return flag;
    }

    /**
     *	post:application/x-www-form-urlencoded 请求方式
     * @param signParam	签名参数
     * @param sendParam	请求表单参数（服务端参与签名）
     * @param clazz	响应数据类型
     * @param <T>
     * @return
     */
    private static <T> ResponseEntity<T> postOrPutFormOpenApi(MultiValueMap<String, String> signParam, MultiValueMap<String, String> sendParam, Class<T> clazz, HttpMethod httpMethod) {
        // HEADER
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.setContentType(MediaType.parseMediaType("application/x-www-form-urlencoded; charset=UTF-8"));
        requestHeaders.set(HttpRequestUtils.AJAX_REQUEST_HEADER, HttpRequestUtils.API_REQUEST_VALUE);
        // ENTITY
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(
                sendParam, requestHeaders);
        return getOpenApiResponse(signParam, sendParam, requestEntity, httpMethod, clazz);
    }

    /**
     *	openapi请求
     * @param signParam	签名参数
     * @param sendParam	请求参数
     * @param requestEntity	请求entity
     * @param httpMethod	请求方式
     * @param clazz	响应数据类型
     * @param <T>
     * @return
     */
    private static <T> ResponseEntity<T> getOpenApiResponse(MultiValueMap<String, String> signParam, MultiValueMap<String, String> sendParam, HttpEntity<?> requestEntity, HttpMethod httpMethod, Class<T> clazz) {
        String appId = signParam.getFirst("appId");
        String appSecret = signParam.getFirst("appSecret");
        String endpoint = signParam.getFirst("endpoint");
        String path = signParam.getFirst("path");
        try {
            // Open API协议
            String sessionUser = OpenApiHelper.getSessionUser(null);

            String queryString = OpenApiHelper.getOpenApiParamsMap(appId, appSecret, null, sessionUser, null, OpenApiHelper.FORMAT_JSON, OpenApiHelper.SIGN_METHOD_MD5, "zh_CN", sendParam);

            // URL
            UriComponents uriComponents = null;
            if (path.toLowerCase().startsWith("http:") || path.startsWith("https://")) {
                uriComponents = UriComponentsBuilder.fromUriString(path).query(queryString).build();
            } else {

                uriComponents = UriComponentsBuilder.fromUriString(endpoint + path).query(queryString).build();
            }
            uriComponents = uriComponents.encode();

            // EXECUTE
            RestTemplate restTemplate = new RestTemplate();
            //如果是返回类型设置为String，则需要设置StringHttpMessageConverter(default Charset "ISO-8859-1")为"UTF-8",解决乱码问题
            if (String.class.equals(clazz)){
                List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
                if(null != messageConverters && !messageConverters.isEmpty()){
                    for(int i=0; i<messageConverters.size(); i++){
                        HttpMessageConverter<?> converter = messageConverters.get(i);
                        if(converter.getClass() == StringHttpMessageConverter.class){
                            messageConverters.remove(converter);
                            messageConverters.add(i, new StringHttpMessageConverter(Charset.forName("UTF-8")));
                            break;
                        }
                    }
                }
            }

            System.out.println("请求地址：\n"+uriComponents.toString());
            //openapi请求
            ResponseEntity<T> responseEntity = restTemplate.exchange(uriComponents.toUri(), httpMethod, requestEntity, clazz);

            HttpStatus status = responseEntity.getStatusCode();

            if (status == HttpStatus.OK || status == HttpStatus.CREATED || status == HttpStatus.ACCEPTED
                    || status == HttpStatus.INTERNAL_SERVER_ERROR) {
                return responseEntity;
            } else {
                throw new OpenApiException("error.openapi.response.status", new Object[] { status });
            }
        } catch (MaculaException e) {
            throw e;
        } catch (Exception e) {
            throw new OpenApiException(String.format("error.openapi.request.execute(%s)", e.getMessage()), e);
        }
    }


}